package com.cykj.pos.util;

import com.alibaba.fastjson.JSONObject;
import com.cykj.pos.domain.dto.BizAgentidAppkeyDTO;
import com.cykj.pos.mapper.BizMerchantReceiverMapper;
import com.cykj.pos.service.IBizMerchantReceiverService;
import com.google.gson.Gson;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * @project: zbh-api
 * @package: vip.zhongbaohui.api.product.saas.core.util
 * @class: SaasSignatureUtil
 * @description: 赢灵签名工具类
 */
@Component
public class SaasSignatureUtil {
    @Resource
    IBizMerchantReceiverService iBizMerchantReceiverService;
    @Resource
    private BizMerchantReceiverMapper bizMerchantReceiverMapper;

    private static Logger logger = LoggerFactory.getLogger(SaasSignatureUtil.class);

    /** 16进制数字字符集 */
    private static String hexString="0123456789ABCDEF";

    private static String timep;

    /**
     * 获取赢灵签名
     *
     * @return
     */
    public static String getSignature(BizAgentidAppkeyDTO bizAgentidAppkeyDTO) throws Exception {
        Map<String,Object> params =new HashMap<String ,Object>();
        timep=System.currentTimeMillis()+"";
        params.put("timestamp",timep);
        params.put("appSecret",bizAgentidAppkeyDTO.getAppsecret());
        params.put("appKey",bizAgentidAppkeyDTO.getAppkey());
        params.put("version",bizAgentidAppkeyDTO.getVersion());
        /** 对加密前的字符串进行sha1 加密 */
        String signString = buildSignString(params);
        /** 对加密前的字符串进行sha1 加密 */
        signString = DigestUtils.sha1Hex(signString).toUpperCase();
        /** 转成16 进制编码，并转为大写字符串 */
        //signString = str2HexStr(signString).toUpperCase();
        return signString;
    }

    /**
     * 生成随机数
     *
     * @return
     */
    public static String getTraceID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 通知验签
     * @param saasPublicEntity
     * @return boolean
     */
    /*public static boolean checkSign(SaasPublicEntity saasPublicEntity) {
        logger.info("赢灵通知验签 原有签名signature："+saasPublicEntity.getSignature()+",参数"+saasPublicEntity);

        *//*生成待签字串 和  sign**//*
        //Map<String, Object> body = JsonUtils.json2Obj(requestBody, Map.class);
        String sign ="";
        try {
            sign = getSignature(saasPublicEntity);
        } catch (Exception e) {
            logger.error("通知验签生成签名失败！",e);
            return false;
        }
        logger.info("生成签名字符串为："+sign);
        return saasPublicEntity.getSignature().equals(sign);
    }*/

    /**
     * 构建签名字符串
     * 将所有参与签名字段按照参数名的字典顺序排序
     * 以参数1 值1 参数2 值2 参数...的顺序拼接，（列如a=1&c=3&b=2 变为a1b2c3））
     * 开发者密钥以appSecret=***按第一步规则拼接到排序字符串中（列如a1b2c3 则变为appSecret***a1b2c3）
     * 按key+排序后的参数+secret,得到加密前字符串
     * @return String
     */
    public static String buildSignString(Map<String, Object> params) {
        if (params == null || params.size() == 0) {
            return "";
        }
        List<String> keys = new ArrayList<>(params.size());

        for (String key : params.keySet()) {
            if (ObjectUtils.isEmpty(params.get(key)))
                continue;
            keys.add(key);
        }
        /*key按照a-z排序**/
        Collections.sort(keys);

        /*key+排序后的参数+secret**/
        StringBuilder buf = new StringBuilder("key");
        /*构建排序后的参数**/
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key).toString();
            /*拼接非空字段**/
            if(StringUtils.isNotBlank(value)) {
                buf.append(key + value);
            }
        }
        buf.append("secret");

        return buf.toString();
    }

    /**
     * 将字符串编码成16进制数字,适用于所有字符（包括中文）
     */
    public static String str2HexStr(String str){
        //根据默认编码获取字节数组
        byte[] bytes=str.getBytes();
        StringBuilder sb=new StringBuilder(bytes.length*2);
        //将字节数组中每个字节拆解成2位16进制整数
        for(int i=0;i<bytes.length;i++){
            sb.append(hexString.charAt((bytes[i]&0xf0)>>4));
            sb.append(hexString.charAt((bytes[i]&0x0f)>>0));
        }
        return sb.toString();
    }

    /**
     * 链接薪龙
     * @param sign
     * @param requestBody
     * @return
     */
    public static JSONObject submit(BizAgentidAppkeyDTO bizAgentidAppkeyDTO,String service, String sign, String requestBody,String token) {
        String url="https://xlapi.51xinlong.com/openapi?service="+service;
        Map<String, String> data = new HashMap<String, String>();
        data.put("timestamp",timep);
        data.put("appKey",bizAgentidAppkeyDTO.getAppkey());
        data.put("signature",sign);
        data.put("version",bizAgentidAppkeyDTO.getVersion());
        data.put("requestBody",requestBody);
        System.out.println(requestBody);
        String result = doPost(url, new Gson().toJson(data),token,bizAgentidAppkeyDTO);
        System.out.println("返回:" + result);
        JSONObject jsonObject =JSONObject.parseObject(result);
        return jsonObject;
    }

    //发送json请求
    public static String doPost(String url, String data,String token,BizAgentidAppkeyDTO bizAgentidAppkeyDTO) {
        //创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = "";
        try {
            //创建http请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
            httpPost.addHeader("Authorization","Bearer "+ token);
            httpPost.addHeader("traceID", bizAgentidAppkeyDTO.getUid());
            httpPost.addHeader("companyid", bizAgentidAppkeyDTO.getCompanyid());
            httpPost.addHeader("mainAccount", bizAgentidAppkeyDTO.getMainAccount());
            //创建请求内容
            String jsonStr = data;
            System.out.println(jsonStr);
            StringEntity entity = new StringEntity(jsonStr, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            result = EntityUtils.toString(response.getEntity(), "utf-8");
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return result;
    }
    public static String getToken(BizAgentidAppkeyDTO bizAgentidAppkeyDTO){
        //创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = "";
        try {
            //创建http请求
            HttpPost httpPost = new HttpPost("https://xlapi.51xinlong.com/jwt/auth/openapi");
            httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
            Map<String, String> data = new HashMap<String, String>();
            data.put("appid",bizAgentidAppkeyDTO.getAppkey());
            data.put("secret",bizAgentidAppkeyDTO.getAppsecret());
            //创建请求内容
            String jsonStr = new Gson().toJson(data);
            StringEntity entity = new StringEntity(jsonStr, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            result = EntityUtils.toString(response.getEntity(), "utf-8");
            JSONObject jsonObject=JSONObject.parseObject(result);
            String token=jsonObject.getString("access_token");
            if(StringUtils.isNotBlank(token)){
                result=token;
            }
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return result;
    }
}
